package br.com.felix.bmt.business;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;

import br.com.felix.bmt.exception.BlogFileWriteException;
import br.com.felix.bmt.exception.ImpossibleToCreateUserException;
import br.com.felix.bmt.exception.ImpossibleToPostException;
import br.com.felix.bmt.model.Post;
import br.com.felix.bmt.model.User;


/**
 * Class that handle all the business logic and takes care of persistence too.
 * */
public class BlogManagement {

	/**
	 * Hard coded is easier to do :)
	 * */
	private static File blogFile = new File("d:\\blogs.ser");

	private ArrayList<Post> lstPosts;
	
	private ArrayList<User> lstUsers;
	
	private static BlogManagement instance;

	
	/**
	 * Private constructor, "reads database".
	 * */
	private BlogManagement() {
		readFile();
	}
	
	
	/**
	 * Never used.
	 * */
	public static void setFile(File bFile){
		blogFile = bFile;
	}
	
	
	/**
	 * Looks like we have a Singleton.
	 * */
	public static BlogManagement instance(){
		if(instance == null){
			instance = new BlogManagement();
		}
		return instance;
	}

	
	/**
	 * Reads the serialized "database".
	 * */
	@SuppressWarnings("unchecked")
	private void readFile() {
		if (blogFile == null)return;
		if (!blogFile.exists()){
			lstPosts = new ArrayList<Post>();
			lstUsers = new ArrayList<User>();
			return;
		}

		FileInputStream fis = null;
		ObjectInputStream ois = null;
		try {
			fis = new FileInputStream(blogFile);
			ois = new ObjectInputStream(fis);
			lstPosts = (ArrayList<Post>) ois.readObject();
			lstUsers = (ArrayList<User>) ois.readObject();
		}
		catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		finally {
			try {
				ois.close();
				fis.close();
			}
			catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}

	
	
	/**
	 * Saves the new post to the database.
	 * */
	public void post(Post p) throws ImpossibleToPostException {
		if(lstPosts == null)lstPosts = new ArrayList<Post>();
		lstPosts.add(p);
		try {
			write();
		}
		catch (BlogFileWriteException e) {
			throw new ImpossibleToPostException("Could not write post.",e);
		}
	}

	
	/**
	 * Rewrites the database.
	 * */
	private void write() throws BlogFileWriteException {
		FileOutputStream fos = null;
		ObjectOutputStream oos = null;
		try {
			if(blogFile.exists())blogFile.delete();
			blogFile.createNewFile();
			fos = new FileOutputStream(blogFile);
			oos = new ObjectOutputStream(fos);
			oos.writeObject(lstPosts);
			oos.writeObject(lstUsers);
		}
		catch (FileNotFoundException e) {
			throw new BlogFileWriteException(e);
		}
		catch (IOException e) {
			throw new BlogFileWriteException(e);
		}
		finally{
			try {
				oos.close();
				fos.close();
			}
			catch (IOException e) {
				throw new BlogFileWriteException(e);
			}
		}
	}
	
	
	/**
	 * Obtains a list of all the posts.
	 * */
	public List<Post> getPosts(User user){
		ArrayList<Post> arrUserPosts = new ArrayList<Post>();
		if(lstPosts==null){
			lstPosts = new ArrayList<Post>();
		}
		for(Post post:lstPosts){
			if(post.getUser().equals(user)){
				arrUserPosts.add(post);
			}
		}
		return arrUserPosts;
	}


	/**
	 * Obtains a list of all the registered users.
	 * */
	public List<User> getUsers() {
		return lstUsers;
	}

	
	/**
	 * Makes input validation, and saves a new User to the database.
	 * */
	public void registerNewUser(User usr) throws ImpossibleToCreateUserException {
		if(usr.name==null || usr.name.length()==0){
			throw new ImpossibleToCreateUserException("Name cannot be empty.");
		}
		if(lstUsers==null){
			lstUsers = new ArrayList<User>();
		}
		if(lstUsers.contains(usr)){
			throw new ImpossibleToCreateUserException("User already exists.");
		}
		else{
			lstUsers.add(usr);
		}
		try {
			write();
		}
		catch (BlogFileWriteException e) {
			lstUsers.remove(usr);
			throw new ImpossibleToCreateUserException("Could not write user to database.",e);
		}
	}

}
